const Card = require("./entity/Card.js");
const Action = require("./entity/Action.js");
const Room = require("./entity/Room.js");
const co = require("co");
module.exports = (() => {
    const shuoshiCards = [Card.A, Card.B, Card.C, Card.D, Card.E, Card.F, Card.G, Card.H, Card.L];
    const boshiCards = [Card.H, Card.I, Card.J, Card.K, Card.L, Card.M, Card.N, Card.Q, Card.Z];
    const daoshiCards = [Card.A, Card.E, Card.I, Card.O, Card.U, Card.H, Card.L, Card.Q, Card.Z].sort(function(a, b) {
        return a - b;
    });
    const lihuCards = [Card.A, Card.H, Card.O, Card.P, Card.Q, Card.R, Card.S, Card.T, Card.U, Card.V, Card.W, Card.X, Card.Y, Card.Z];
    const lehuCards = [Card.E, Card.L, Card.O, Card.P, Card.Q, Card.R, Card.S, Card.T, Card.U, Card.V, Card.W, Card.X, Card.Y, Card.Z];
    const dinghuCards = [Card.E, Card.H, Card.O, Card.P, Card.Q, Card.R, Card.S, Card.T, Card.U, Card.V, Card.W, Card.X, Card.Y, Card.Z];
    const longfengCards = [Card.A, Card.B, Card.C, Card.D, Card.E, Card.F, Card.G, Card.H, Card.I, Card.J, Card.K, Card.L, Card.M, Card.N];

    function isMenqing(cards, opts) {
        let r = opts.pengpenghu || opts.qixiaodui;
        if (!r) {
            return false;
        }
        for (let card of cards) {
            if (card.status != Card.STATUS_ONHAND && card.status != Card.STATUS_ANGANG && card.status != Card.STATUS_BEIDA) {
                return false;
            }
        }
        return true;
    }

    function is33Group(cards) {
        if (cards.length == 0) {
            return {
                result: true,
                count: 0
            };
        }
        if (cards.length % 3 != 0) {
            return {
                result: false,
                count: 0
            };
        }
        //第1个牌和第2个牌相同的情况
        if (cards[0].value == cards[1].value) {
            //第3个牌也要和第一个牌相同，则这3个是正确的组合
            if (cards[1].value == cards[2].value) {
                return {
                    result: true,
                    count: 3
                };
            } else if (cards.length >= 6 && (cards[0].value == cards[1].value && cards[1].value == cards[2].value - 1 && cards[2].value == cards[3].value && cards[3].value == cards[4].value - 1 && cards[4].value == cards[5].value)) {
                return {
                    result: true,
                    count: 6
                };
            } else {
                return {
                    result: false,
                    count: 0
                };
            }
        } else { //第1个牌和第2个牌不同的情况
            if (cards[0].value == cards[1].value - 1) { //如果第2个牌比第一个牌大1
                //第三个牌也比第二个牌大1，则这3个是正确的组合
                if (cards[1].value == cards[2].value - 1) {
                    return {
                        result: true,
                        count: 3
                    };
                } else if (cards[1].value == cards[2].value) { //第2个牌和第3个相同的情况
                    if (cards.length <= 3) { //长度小于等于3直接false
                        return {
                            result: false,
                            count: 0
                        };
                    } else if (cards.length >= 6 &&
                        (cards[1].value == cards[4].value && cards[4].value == cards[5].value - 1) ||
                        (cards[3].value == cards[4].value && cards[1].value == cards[2].value && cards[2].value == cards[3].value - 1) && cards[4].value == cards[5].value - 1) { //第4个和第5个相同，第6个比第5个大1，第4个比第3个大1，则这6个是正确的组合
                        return {
                            result: true,
                            count: 6
                        };
                    } else if (cards[2].value == cards[3].value && cards.length >= 9) { //第3个牌和第4个也相同的情况
                        if (cards[3].value == cards[4].value - 1 &&
                            cards[4].value == cards[6].value &&
                            cards[6].value == cards[7].value - 1 &&
                            cards[7].value == cards[8].value) { //第5张牌必须比第4张牌大1,第7张牌必须和第5张一样，第8，9张牌必须比第7张大1，并且一样
                            return {
                                result: true,
                                count: 9
                            };
                        } else {
                            return {
                                result: false,
                                count: 0
                            };
                        }

                    } else {
                        return {
                            result: false,
                            count: 0
                        };
                    }
                } else {
                    return {
                        result: false,
                        count: 0
                    };
                }
            } else {
                return {
                    result: false,
                    count: 0
                };
            }
        }
    }
    return {
        shuffledAllCards: function() {
            return Card.allCards.shuffle();
        },
        alpha: {
            canPeng: function(cards, card) {
                //只能用手里的牌碰
                cards = cards.filter((_card) => {
                    return _card.status == Card.STATUS_ONHAND;
                }).sort((a, b) => {
                    return a.value - b.value;
                });
                let actions = [];
                if (cards.length < 3 || cards.length % 3 != 2) {
                    return {
                        actions: actions
                    };
                }
                //只要有对子就能碰
                for (let i = 0; i < cards.length - 1; i++) {
                    let _card = cards[i];
                    let _card2 = cards[i + 1];
                    if (_card.value == card.value && _card.value == _card2.value) {
                        actions.push({
                            type: Action.ACTIONS_PENG,
                            myCards: [_card, _card2],
                            otherCard: card
                        });
                        break;
                    }
                }
                return {
                    actions: actions
                };
            },
            canMingGang: function(cards, card) {
                //只能用手里的牌杠
                cards = cards.filter((_card) => {
                    return _card.status == Card.STATUS_ONHAND;
                }).sort((a, b) => {
                    return a.value - b.value;
                });
                let actions = [];
                if (cards.length < 4 || cards.length % 3 != 2) {
                    return {
                        actions: actions
                    };
                }
                for (let i = 0; i < cards.length - 2; i++) {
                    let _card = cards[i];
                    let _card1 = cards[i + 1];
                    let _card2 = cards[i + 2];
                    if (_card.value == card.value && _card.value == _card2.value) {
                        actions.push({
                            type: Action.ACTIONS_MINGGANG,
                            myCards: [_card, _card1, _card2],
                            otherCard: card
                        });
                        break;
                    }
                }
                return {
                    actions: actions
                };
            },
            canAnGang: function(cards) {
                //只能用手里的牌杠
                cards = cards.filter((_card) => {
                    return _card.status == Card.STATUS_ONHAND;
                }).sort((a, b) => {
                    return a.value - b.value;
                });
                let actions = [];
                if (cards.length < 5 || cards.length % 3 != 0) {
                    return {
                        actions: actions
                    };
                }
                for (let i = 0; i < cards.length - 3; i++) {
                    let _card = cards[i];
                    let _card1 = cards[i + 1];
                    let _card2 = cards[i + 2];
                    let _card3 = cards[i + 3];
                    if (_card.value == _card3.value) {
                        actions.push({
                            type: Action.ACTIONS_ANGANG,
                            myCards: [_card, _card1, _card2, _card3]
                        });
                    }
                }
                return {
                    actions: actions
                };
            },
            canJiaGang: function(cards, card) {
                //只能用碰的牌加杠
                cards = cards.filter((_card) => {
                    return _card.status == Card.STATUS_PENG;
                }).sort((a, b) => {
                    return a.value - b.value;
                });
                let actions = [];
                let uniqueValues = (() => {
                    let r = [];
                    for (let i = 0; i < cards.length; i++) {
                        if (i % 3 == 0) {
                            let _card = cards[i];
                            r.push(_card.value);
                        }
                    }
                    return r;
                })();
                for (let value of uniqueValues) {
                    if (card.value == value) {
                        let myCards = cards.filter((_card) => {
                            return _card.value == value;
                        });
                        actions.push({
                            type: Action.ACTIONS_JIAGANG,
                            myCards: myCards,
                            otherCard: card
                        });
                    }
                }
                return {
                    actions: actions
                };
            },
            isXueShi: function(cards) {
                cards = cards.filter((_card) => {
                    return _card.status != Card.STATUS_INIT;
                }).sort((a, b) => {
                    return a.value - b.value;
                });
                let handCards = cards.filter((card) => {
                    return card.status == Card.STATUS_ONHAND;
                });
                if (handCards.length % 3 != 0) {
                    return false;
                }
                //手上的牌都是三个的
                let doubleCount = 0;
                for (let tmpCard of handCards) {
                    let sameCards = handCards.filter((_card) => {
                        return _card.value == tmpCard.value;
                    });
                    if (sameCards.length != 3) {
                        return false;
                    }
                }
                return true;
            },
            isShuoShi: function(cards) {
                let handCards = cards.filter((card) => {
                    return card.status == Card.STATUS_ONHAND;
                }).map((card) => {
                    return card.value;
                }).sort(function(a, b) {
                    return a - b;
                });
                return shuoshiCards.toString() == handCards.toString();
            },
            isBoShi: function(cards) {
                let handCards = cards.filter((card) => {
                    return card.status == Card.STATUS_ONHAND;
                }).map((card) => {
                    return card.value;
                }).sort(function(a, b) {
                    return a - b;
                });
                return boshiCards.toString() == handCards.toString();
            },
            isDaoShi: function(cards) {
                let handCards = cards.filter((card) => {
                    return card.status == Card.STATUS_ONHAND;
                }).map((card) => {
                    return card.value;
                }).sort(function(a, b) {
                    return a - b;
                });
                return daoshiCards.toString() == handCards.toString();
            },
            canZiMo: function(cards) {
                cards = cards.sort((a, b) => {
                    return a.value - b.value;
                });
                return this.isXueYuan(cards) || this.isXueShi(cards) || this.isShuoShi(cards) || this.isBoShi(cards) || this.isDaoShi(cards);
            },
            zimo: function(cards, /**剩余的牌**/ remainCards, /**无效参数**/ birdCount, /**无效参数**/ isBaoTing, isGangBao, /**无效参数**/ maxBase, isTianHu, /**无效参数**/ zimoCard) {
                cards = cards.filter((_card) => {
                    return _card.status != Card.STATUS_BEIDA;
                }).sort((a, b) => {
                    return a.value - b.value;
                });
                let menzis = [];
                let point = 0;
                let factor = 0;
                if (this.isXueShi(cards)) {
                    menzis.push(Card.Alpha.MENZI_XUESHI);
                    point = 4;
                    factor += 4;
                } else if (this.isShuoShi(cards)) {
                    menzis.push(Card.Alpha.MENZI_SHUOSHI);
                    point = 6;
                    factor += 6;
                } else if (this.isBoShi(cards)) {
                    menzis.push(Card.Alpha.MENZI_BOSHI);
                    point = 8;
                    factor += 8;
                } else if (this.isDaoShi(cards)) {
                    menzis.push(Card.Alpha.MENZI_DAOSHI);
                    point = 20;
                    factor += 20;
                } else if (this.isXueYuan(cards)) {
                    menzis.push(Card.Alpha.MENZI_XUEYUAN);
                    point = 2;
                    factor += 2;
                }
                if (isGangBao) {
                    menzis.push(Card.MENZI_GANGBAO);
                    factor += 3;
                }
                if (isTianHu) {
                    menzis.push(Card.MENZI_TIANHU);
                    factor += 3;
                }
                if (remainCards.length < 1) {
                    menzis.push(Card.MENZI_HAIDI);
                }
                return {
                    menzis,
                    base: point * factor,
                    point,
                    factor
                };
            },
            canJiePao: function(cards, card) {
                card.status = Card.STATUS_ONHAND;
                let _cards = cards.concat(card).sort((a, b) => {
                    return a.value - b.value;
                });
                return this.isXueShi(_cards) || this.isShuoShi(_cards) || this.isBoShi(_cards) || this.isDaoShi(_cards);
            },
            isXueYuan: function(cards) {
                let handCards = cards.filter((card) => {
                    return card.status == Card.STATUS_ONHAND;
                }).sort((a, b) => {
                    return a.value - b.value;
                });
                if (handCards.length % 3 != 0) {
                    return false;
                }
                let result = is33Group(handCards);
                while (result.result) {
                    handCards = handCards.splice(result.count);
                    result = is33Group(handCards);
                    if (result.result && result.count == 0) {
                        return true;
                    }
                }
                return false;
            },
            //返回可以打哪些牌，才可以听牌
            tingCards: function(cards) {
                let result = {
                    r: false
                };
                if (cards.length == 9) {
                    let tingCards = [];
                    for (let i = 0; i < cards.length; i++) {
                        let _cards = cards.clone();
                        let card = _cards[i];
                        _cards = _cards.removeAt(i);
                        if (this.canTing(_cards)) {
                            tingCards.push(card);
                        }
                    }
                    if (tingCards.length) {
                        result.r = true;
                        result.tingCards = tingCards;
                    }
                } else if (cards.length == 8) {
                    if (this.canTing(cards)) {
                        result.r = true;
                    }
                }
                return result;
            },
            canTing: function( /*没有摸牌之前的牌，如8张*/ cards) {
                return false;
            },
            jiepao: function(cards, card, /*无用参数*/ isBaoTing, isQiangGang) {
                card.status = Card.STATUS_ONHAND; //把这个牌当成自己手中的牌
                cards = cards.concat(card).filter((_card) => {
                    return _card.status != Card.STATUS_BEIDA;
                }).sort((a, b) => {
                    return a.value - b.value;
                });
                let menzis = [];
                let point = 0;
                let factor = 0;
                if (this.isXueShi(cards)) {
                    menzis.push(Card.Alpha.MENZI_XUESHI);
                    point = 4;
                    factor += 4;
                } else if (this.isShuoShi(cards)) {
                    menzis.push(Card.Alpha.MENZI_SHUOSHI);
                    point = 6;
                    factor += 6;
                } else if (this.isBoShi(cards)) {
                    menzis.push(Card.Alpha.MENZI_BOSHI);
                    point = 8;
                    factor += 8;
                } else if (this.isDaoShi(cards)) {
                    menzis.push(Card.Alpha.MENZI_DAOSHI);
                    point = 10;
                    factor += 10;
                }
                if (isQiangGang) {
                    menzis.push(Card.MENZI_QIANGGANG);
                    factor += 3;
                }
                return {
                    menzis,
                    base: point * factor,
                    point,
                    factor
                };
            },
        },
        beta: {
            qixiaodui: function(cards) {
                cards = cards.filter((_card) => {
                    return _card.status != Card.STATUS_INIT;
                });
                cards = cards.filter((_card) => {
                    return _card.status == Card.STATUS_ONHAND;
                }).sort((a, b) => {
                    return a.value - b.value;
                });
                if (cards.length != 14) {
                    return false;
                }
                let isQiXiaoDui = (() => {
                    for (let i = 0; i < cards.length; i += 2) {
                        let tmpCard = cards[i];
                        let tmpCard2 = cards[i + 1];
                        if (tmpCard.value != tmpCard2.value) {
                            return false;
                        }
                    }
                    return true;
                })();
                if (isQiXiaoDui) {
                    let count = 0; //组成4个的数量，数量+1代表多一个豪华七小对
                    for (let i = 0; i < cards.length - 3; i += 2) {
                        let tmpCard = cards[i];
                        let tmpCard2 = cards[i + 2];
                        if (tmpCard.value == tmpCard2.value) {
                            count++;
                        }
                    }
                    return {
                        count: count
                    };
                } else {
                    return false;
                }
            },
            pengpenghu: function(cards) {
                cards = cards.filter((_card) => {
                    return _card.status != Card.STATUS_INIT;
                });
                let handCards = cards.filter((card) => {
                    return card.status == Card.STATUS_ONHAND;
                }).sort((a, b) => {
                    return a.value - b.value;
                });
                if (handCards.length % 3 != 2) {
                    return false;
                }
                //手上的牌存在一个对子的情况，其他的都是三个的
                let doubleCount = 0;
                for (let tmpCard of handCards) {
                    let sameCards = handCards.filter((_card) => {
                        return _card.value == tmpCard.value;
                    });
                    if (sameCards.length == 2) {
                        doubleCount++;
                    } else if (sameCards.length == 3) {

                    } else {
                        return false;
                    }
                }
                return doubleCount == 2;
            },
            canPihu: function(cards) {
                let handCards = cards.filter((card) => {
                    return card.status == Card.STATUS_ONHAND;
                }).sort((a, b) => {
                    return a.value - b.value;
                });
                if (handCards.length % 3 != 2) {
                    return false;
                }
                var cardMap = {};
                for (let tmpCard of handCards) {
                    if (cardMap[tmpCard.value]) {
                        cardMap[tmpCard.value]++;
                    } else {
                        cardMap[tmpCard.value] = 1;
                    }
                }
                for (let k in cardMap) {
                    let count = 0;
                    let _cards = handCards.clone();
                    //只能出现一个对子，所以遍历每种对子出现的情况
                    let v = cardMap[k];
                    if (v >= 2) {
                        //去掉对子后，要满足剩下的牌三三成组
                        _cards = handCards.filter((_card) => {
                            if (_card.value == k) {
                                count++;
                            }
                            if (count > 2) {
                                return true;
                            }
                            return _card.value != k;
                        });
                        if (_cards.length == 0) {
                            //空数组说明去掉了一个对子后手中无牌了，所以胡牌
                            return true;
                        }
                        //判断是否三三成组
                        let result = is33Group(_cards);
                        while (result.result) {
                            _cards = _cards.splice(result.count);
                            result = is33Group(_cards);
                            if (result.result && result.count == 0) {
                                return true;
                            }
                        }
                    }
                }
                return false;
            },
            //清一色
            qingyise: function(cards) {
                cards = cards.filter((_card) => {
                    return _card.status != Card.STATUS_BEIDA;
                });
                if (cards.length <= 2) {
                    return false;
                }
                for (let i = 0; i < cards.length - 1; i++) {
                    let card = cards[i];
                    let card2 = cards[i + 1];
                    if (Card.getType(card) != Card.getType(card2)) {
                        return false;
                    }
                }
                return true;
            },
            lihu: function(cards) {
                let handCards = cards.filter((card) => {
                    return card.status == Card.STATUS_ONHAND;
                }).map((card) => {
                    return card.value;
                }).sort(function(a, b) {
                    return a - b;
                });
                return lihuCards.toString() == handCards.toString();
            },
            lehu: function(cards) {
                let handCards = cards.filter((card) => {
                    return card.status == Card.STATUS_ONHAND;
                }).map((card) => {
                    return card.value;
                }).sort(function(a, b) {
                    return a - b;
                });
                return lehuCards.toString() == handCards.toString();
            },
            dinghu: function(cards) {
                let handCards = cards.filter((card) => {
                    return card.status == Card.STATUS_ONHAND;
                }).map((card) => {
                    return card.value;
                }).sort(function(a, b) {
                    return a - b;
                });
                return dinghuCards.toString() == handCards.toString();
            },
            longfeng: function(cards) {
                let handCards = cards.filter((card) => {
                    return card.status == Card.STATUS_ONHAND;
                }).map((card) => {
                    return card.value;
                }).sort(function(a, b) {
                    return a - b;
                });
                return longfengCards.toString() == handCards.toString();
            },
            canZiMo: function(cards) {
                cards = cards.sort((a, b) => {
                    return a.value - b.value;
                });
                return !!this.qixiaodui(cards) || this.pengpenghu(cards) || this.lihu(cards) || this.lehu(cards) || this.dinghu(cards) || this.canPihu(cards) || this.longfeng(cards);
            },
            canJiePao: function(cards, card, isBaoTing, isQiangGang) {
                card.status = Card.STATUS_ONHAND;
                let _cards = cards.concat(card).sort((a, b) => {
                    return a.value - b.value;
                });
                let qixiaodui = !!this.qixiaodui(_cards);
                let pengpenghu = this.pengpenghu(_cards);
                let qingyise = this.qingyise(_cards);
                return qixiaodui || pengpenghu || this.lihu(_cards) || this.longfeng(_cards) || this.lehu(_cards) || this.dinghu(_cards) || ((!!isBaoTing || !!isQiangGang || qingyise) && this.canPihu(_cards));
            },
            canTing: function(cards) {
                return false;
            },
            //返回可以打哪些牌，才可以听牌
            tingCards: function( /*摸牌之后的牌,如14张*/ cards) {
                let result = {
                    r: false
                };
                if (cards.length == 14) {
                    let tingCards = [];
                    for (let i = 0; i < cards.length; i++) {
                        let _cards = cards.clone();
                        let card = _cards[i];
                        _cards = _cards.removeAt(i);
                        if (this.canTing(_cards)) {
                            tingCards.push(card);
                        }
                    }
                    if (tingCards.length) {
                        result.r = true;
                        result.tingCards = tingCards;
                    }
                } else if (cards.length == 13) {
                    if (this.canTing(cards)) {
                        result.r = true;
                    }
                }
                return result;
            },
            jiepao: function(cards, card, /*无效参数*/ isBaoTing, isQiangGang) {
                card.status = Card.STATUS_ONHAND; //把这个牌当成自己手中的牌
                cards = cards.concat(card).filter((_card) => {
                    return _card.status != Card.STATUS_BEIDA;
                }).sort((a, b) => {
                    return a.value - b.value;
                });
                let menzis = [];
                let factor = 0;
                let point = 0;
                let res = this.qixiaodui(cards);
                let qixiaodui = false;
                if (res) {
                    point = 5;
                    factor += 5;
                    qixiaodui = true;
                    if (res.count == 0) {
                        menzis.push(Card.Beta.MENZI_QIXIAODUI);
                    } else if (res.count == 1) {
                        menzis.push(Card.Beta.MENZI_SQIXIAODUI);
                        factor += 3;
                    } else if (res.count == 2) {
                        menzis.push(Card.Beta.MENZI_SQIXIAODUI);
                        factor += 6;
                    } else if (res.count == 3) {
                        menzis.push(Card.Beta.MENZI_SQIXIAODUI);
                        factor += 9;
                    }
                }
                let pengpenghu = this.pengpenghu(cards);
                if (pengpenghu) {
                    menzis.push(Card.Beta.MENZI_DAPENGDUI);
                    factor += 3;
                    point = 3;
                }
                let lihu = this.lihu(cards);
                if (lihu) {
                    menzis.push(Card.Beta.MENZI_LIHU);
                    factor += 13;
                    point = 13;
                }
                let lehu = this.lehu(cards);
                if (lehu) {
                    menzis.push(Card.Beta.MENZI_LEHU);
                    factor += 13;
                    point = 13;
                }
                let dinghu = this.dinghu(cards);
                if (dinghu) {
                    menzis.push(Card.Beta.MENZI_DINGHU);
                    factor += 13;
                    point = 13;
                }
                let longfeng = this.longfeng(cards);
                if (longfeng) {
                    menzis.push(Card.Beta.MENZI_LONGFENG);
                    factor += 13;
                    point = 13;
                }
                let isQingyise = this.qingyise(cards);
                let pushMenzi = () => {
                    if (isQingyise) {
                        menzis.push(Card.Beta.MENZI_QINGYISE);
                        factor += 5;
                        if (point < 5) {
                            point = 5;
                        }
                    }
                    if (isQiangGang) {
                        menzis.push(Card.Beta.MENZI_QIANGGANG);
                        factor += 3;
                    }
                };
                if (menzis.length == 0) { //屁胡必须要报听或者是抢杠胡
                    if ((isQingyise || isQiangGang) && this.canPihu(cards)) {
                        if (point < 2) {
                            point = 2;
                        }
                        pushMenzi();
                    }
                } else {
                    let len = menzis.length;
                    pushMenzi();
                }
                let base = factor * point;
                let ret = {
                    menzis,
                    base,
                    factor,
                    point
                };
                return ret;
            },
            zimo: function(cards, /**剩余的牌**/ remainCards, /**无效参数**/ birdCount, /**无效参数**/ isBaoTing, isGangBao, /**无效参数**/ maxBase, isTianHu, /**无效参数**/ zimoCard) {
                let menzis = [];
                let factor = 0;
                let point = 0;
                let qixiaodui = this.qixiaodui(cards);
                if (qixiaodui) {
                    menzis.push(Card.Beta.MENZI_QIXIAODUI);
                    factor += 5;
                    point = 5;
                }
                let pengpenghu = this.pengpenghu(cards);
                if (pengpenghu) {
                    menzis.push(Card.Beta.MENZI_DAPENGDUI);
                    factor += 3;
                    point = 3;
                }
                let lihu = this.lihu(cards);
                if (lihu) {
                    menzis.push(Card.Beta.MENZI_LIHU);
                    factor += 13;
                    point = 13;
                }
                let lehu = this.lehu(cards);
                if (lehu) {
                    menzis.push(Card.Beta.MENZI_LEHU);
                    factor += 13;
                    point = 13;
                }
                let dinghu = this.dinghu(cards);
                if (dinghu) {
                    menzis.push(Card.Beta.MENZI_DINGHU);
                    factor += 13;
                    point = 13;
                }
                let longfeng = this.longfeng(cards);
                if (longfeng) {
                    menzis.push(Card.Beta.MENZI_LONGFENG);
                    factor += 13;
                    point = 13;
                }
                if (this.canPihu(cards)) {
                    if (point == 0) {
                        menzis.push(Card.Beta.MENZI_PINGHU);
                        point = 2;
                        factor = 2;
                    }
                }
                if (point > 0) {
                    let isQingyise = this.qingyise(cards);
                    if (isQingyise) {
                        menzis.push(Card.Beta.MENZI_QINGYISE);
                        factor += 5;
                    }
                    if (isGangBao) {
                        menzis.push(Card.MENZI_GANGBAO);
                        factor += 3;
                    }
                    if (isTianHu) {
                        menzis.push(Card.MENZI_TIANHU);
                        factor += 3;
                    }
                }
                let base = factor * point;
                let ret = {
                    menzis,
                    base,
                    factor,
                    point
                };
                return ret;
            },
            canPeng: function(cards, card) {
                //只能用手里的牌碰
                cards = cards.filter((_card) => {
                    return _card.status == Card.STATUS_ONHAND;
                }).sort((a, b) => {
                    return a.value - b.value;
                });
                let actions = [];
                if (cards.length < 4 || cards.length % 3 != 1) {
                    return {
                        actions: actions
                    };
                }
                //只要有对子就能碰
                for (let i = 0; i < cards.length - 1; i++) {
                    let _card = cards[i];
                    let _card2 = cards[i + 1];
                    if (_card.value == card.value && _card.value == _card2.value) {
                        actions.push({
                            type: Action.ACTIONS_PENG,
                            myCards: [_card, _card2],
                            otherCard: card
                        });
                        break;
                    }
                }
                return {
                    actions: actions
                };
            },
            canMingGang: function(cards, card) {
                //只能用手里的牌杠
                cards = cards.filter((_card) => {
                    return _card.status == Card.STATUS_ONHAND;
                }).sort((a, b) => {
                    return a.value - b.value;
                });
                let actions = [];
                if (cards.length < 4 || cards.length % 3 != 1) {
                    return {
                        actions: actions
                    };
                }
                for (let i = 0; i < cards.length - 2; i++) {
                    let _card = cards[i];
                    let _card1 = cards[i + 1];
                    let _card2 = cards[i + 2];
                    if (_card.value == card.value && _card.value == _card2.value) {
                        actions.push({
                            type: Action.ACTIONS_MINGGANG,
                            myCards: [_card, _card1, _card2],
                            otherCard: card
                        });
                        break;
                    }
                }
                return {
                    actions: actions
                };
            },
            canAnGang: function(cards) {
                //只能用手里的牌杠
                cards = cards.filter((_card) => {
                    return _card.status == Card.STATUS_ONHAND;
                }).sort((a, b) => {
                    return a.value - b.value;
                });
                let actions = [];
                if (cards.length < 5 || cards.length % 3 != 2) {
                    return {
                        actions: actions
                    };
                }
                for (let i = 0; i < cards.length - 3; i++) {
                    let _card = cards[i];
                    let _card1 = cards[i + 1];
                    let _card2 = cards[i + 2];
                    let _card3 = cards[i + 3];
                    if (_card.value == _card3.value) {
                        actions.push({
                            type: Action.ACTIONS_ANGANG,
                            myCards: [_card, _card1, _card2, _card3]
                        });
                    }
                }
                return {
                    actions: actions
                };
            },
            canJiaGang: function(cards, card) {
                //只能用碰的牌加杠
                cards = cards.filter((_card) => {
                    return _card.status == Card.STATUS_PENG;
                }).sort((a, b) => {
                    return a.value - b.value;
                });
                let uniqueValues = (() => {
                    let r = [];
                    for (let i = 0; i < cards.length; i++) {
                        if (i % 3 == 0) {
                            let _card = cards[i];
                            r.push(_card.value);
                        }
                    }
                    return r;
                })();
                let actions = [];
                for (let value of uniqueValues) {
                    if (card.value == value) {
                        let myCards = cards.filter((_card) => {
                            return _card.value == value;
                        });
                        actions.push({
                            type: Action.ACTIONS_JIAGANG,
                            myCards: myCards,
                            otherCard: card
                        });
                    }
                }
                return {
                    actions: actions
                };
            },
        },
    };
})();
